package impl

import (
	"context"
	"fmt"
	"time"

	"github.com/infraboard/mcube/v2/ioc"
	"github.com/infraboard/mcube/v2/ioc/config/datasource"
	"gitlab.com/go-course-project/go17/vblog/apps/blog"
	"gitlab.com/go-course-project/go17/vblog/middleware"
)

func init() {
	ioc.Controller().Registry(&BlogServiceImpl{})
}

// 定义一个struct, 用于实现 UserService就是刚才定义的接口
// 怎么才能判断这个结构体没有实现这个接口
type BlogServiceImpl struct {
	ioc.ObjectImpl
}

func (i *BlogServiceImpl) Name() string {
	return blog.AppName
}

// CreateBlog implements blog.Service.
func (b *BlogServiceImpl) CreateBlog(ctx context.Context, in *blog.CreateBlogRequest) (*blog.Blog, error) {
	ins, err := blog.NewBlog(in)
	if err != nil {
		return nil, err
	}

	// 冲上下文中补充 创建人
	tk := middleware.GetTokenFromCtx(ctx)
	if tk != nil {
		ins.CreateBy = tk.RefUserName
	}

	err = datasource.DBFromCtx(ctx).Create(ins).Error
	if err != nil {
		return nil, err
	}

	return ins, nil
}

// QueryBlog implements blog.Service.
func (b *BlogServiceImpl) QueryBlog(ctx context.Context, in *blog.QueryBlogRequest) (*blog.BlogSet, error) {
	query := datasource.DBFromCtx(ctx).Model(&blog.Blog{})
	if in.Keywords != "" {
		query = query.Where("title LIKE ?", "%"+in.Keywords+"%")
	}
	if in.Stage != nil {
		query = query.Where("stage = ?", in.Stage)
	}
	if in.CreateBy != "" {
		query = query.Where("create_by = ?", in.CreateBy)
	}
	if in.Category != "" {
		query = query.Where("category = ?", in.Category)
	}
	for k, v := range in.Tags {
		query = query.Where(fmt.Sprintf("tags->>'$.%s' = ?", k), v)
	}
	set := blog.NewBlogSet()

	// COUNT
	if err := query.Count(&set.Total).Error; err != nil {
		return nil, err
	}

	// 处理分页
	err := query.Order("created_at DESC").Offset(int(in.Offset())).Limit(int(in.PageSize)).Find(&set.Items).Error
	if err != nil {
		return nil, err
	}
	return set, nil
}

// DeleteBlog implements blog.Service.
func (b *BlogServiceImpl) DeleteBlog(ctx context.Context, in *blog.DeleteBlogRequest) error {
	time.Sleep(2 * time.Second)
	ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id))
	if err != nil {
		return err
	}
	return datasource.DBFromCtx(ctx).Where("id = ?", ins.Id).Delete(ins).Error
}

// DescribeBlog implements blog.Service.
func (b *BlogServiceImpl) DescribeBlog(ctx context.Context, in *blog.DescribeBlogRequest) (*blog.Blog, error) {
	ins := &blog.Blog{}
	err := datasource.DBFromCtx(ctx).Where("id = ?", in.Id).First(ins).Error
	if err != nil {
		return nil, err
	}
	return ins, nil
}

// PublishBlog implements blog.Service.
func (b *BlogServiceImpl) PublishBlog(ctx context.Context, in *blog.PublishBlogRequest) (*blog.Blog, error) {
	ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id))
	if err != nil {
		return nil, err
	}

	ins.Stage = in.Stage

	err = b.update(ctx, ins)
	if err != nil {
		return nil, err
	}
	return ins, nil
}

// UpdateBlog implements blog.Service.
func (b *BlogServiceImpl) UpdateBlog(ctx context.Context, in *blog.UpdateBlogRequest) (*blog.Blog, error) {
	ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id))
	if err != nil {
		return nil, err
	}

	// 全量更新
	ins.CreateBlogRequest = in.CreateBlogRequest
	if err := ins.Validate(); err != nil {
		return nil, err
	}

	err = b.update(ctx, ins)
	if err != nil {
		return nil, err
	}

	return ins, nil
}
